// functions/api/[[path]].ts

import { Hono } from 'hono';
import { cors } from 'hono/cors';

type Env = {
  DB: D1Database;
  APP_PASSWORD: string;
};

const app = new Hono<{ Bindings: Env }>();

app.use('*', cors());

// Middleware for authentication (example, you might want to improve this)
// For simplicity, we are not applying auth middleware to all routes yet.
// You could add this to specific routes that need protection.
const authMiddleware = async (c, next) => {
  // This is a placeholder for a more robust auth system
  // e.g., checking a token from the header
  await next();
};


/**
 * 接口 0: 处理登录请求 (POST /api/login)
 */
app.post('/api/login', async (c) => {
  try {
    const { password } = await c.req.json<{ password: string }>();
    const correctPassword = c.env.APP_PASSWORD;

    if (!correctPassword) {
      return c.json({ success: false, error: '系统未配置密码' }, 500);
    }
    if (password === correctPassword) {
      return c.json({ success: true });
    } else {
      return c.json({ success: false, error: '密码错误' }, 401);
    }
  } catch (e) {
    return c.json({ success: false, error: '无效的请求' }, 400);
  }
});

/**
 * 接口 1: 处理打卡和补打卡请求 (POST /api/checkin)
 * - 如果没有提供 date, 则为今天打卡
 * - 如果提供了 date (YYYY-MM-DD), 则为指定日期补打卡
 */
app.post('/api/checkin', async (c) => {
  try {
    const body = await c.req.json<{ timestamp?: string; remarks?: string }>();
    const targetTimestampStr = body.timestamp;
    const remarks = body.remarks || null; // Get remarks, default to null if not provided

    let timestamp;
    if (targetTimestampStr) {
      // 补打卡: 使用前端发送的完整时间戳
      timestamp = new Date(targetTimestampStr).toISOString();
    } else {
      // 正常打卡: 使用当前时间
      timestamp = new Date().toISOString();
    }

    await c.env.DB.prepare(
      `INSERT INTO checkin_logs (timestamp, remarks) VALUES (?, ?)`
    ).bind(timestamp, remarks).run();

    return c.json({ success: true });
  } catch (e) {
    console.error('Check-in error:', e);
    return c.json({ success: false, error: e.message }, 500);
  }
});

/**
 * 接口 2: 获取指定月份的打卡数据 (GET /api/data)
 */
app.get('/api/data', async (c) => {
  const { month } = c.req.query(); // "YYYY-MM"
  if (!month || !/^\d{4}-\d{2}$/.test(month)) {
    return c.json({ success: false, error: '无效的月份格式，请使用 YYYY-MM' }, 400);
  }
  try {
    const { results } = await c.env.DB.prepare(
      `SELECT 
         date(timestamp, '+8 hours') as checkin_date, 
         COUNT(*) as count
       FROM checkin_logs 
       WHERE strftime('%Y-%m', timestamp, '+8 hours') = ?1
       GROUP BY checkin_date`
    ).bind(month).all();
    
    const dataMap = results.reduce((acc, row) => {
      acc[row.checkin_date] = row.count;
      return acc;
    }, {});

    return c.json({ success: true, data: dataMap });
  } catch (e) {
    console.error('Get data error:', e);
    return c.json({ success: false, error: e.message }, 500);
  }
});

/**
 * 接口 3: 获取指定日期的详细打卡记录 (GET /api/details)
 * 返回每条记录的 id 和 timestamp
 */
app.get('/api/details', async (c) => {
  const { date } = c.req.query();
  if (!date || !/^\d{4}-\d{2}-\d{2}$/.test(date)) {
    return c.json({ success: false, error: '无效的日期格式，请使用 YYYY-MM-DD' }, 400);
  }
  try {
    const { results } = await c.env.DB.prepare(
      `SELECT id, timestamp, remarks FROM checkin_logs 
       WHERE date(timestamp, '+8 hours') = ?1 
       ORDER BY timestamp DESC`
    ).bind(date).all<{ id: number; timestamp: string; remarks: string }>();

    const records = results.map(row => ({
      id: row.id,
      time: new Date(row.timestamp).toLocaleTimeString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false }),
      remarks: row.remarks
    }));

    return c.json({ success: true, records: records });
  } catch (e) {
    console.error('Get details error:', e);
    return c.json({ success: false, error: e.message }, 500);
  }
});

/**
 * 接口 4: 删除一条打卡记录 (DELETE /api/checkin)
 */
app.delete('/api/checkin', async (c) => {
    try {
        const { id } = await c.req.json<{ id: number }>();
        if (!id) {
            return c.json({ success: false, error: '需要提供记录 ID' }, 400);
        }

        const { success } = await c.env.DB.prepare(
            `DELETE FROM checkin_logs WHERE id = ?`
        ).bind(id).run();

        if (success) {
            return c.json({ success: true });
        } else {
            return c.json({ success: false, error: '删除失败或记录不存在' }, 500);
        }
    } catch (e) {
        console.error('Delete error:', e);
        return c.json({ success: false, error: e.message }, 500);
    }
});

/**
 * 接口 5: 编辑一条打卡记录的时间 (PUT /api/checkin)
 */
app.put('/api/checkin', async (c) => {
    try {
        const { id, new_timestamp, remarks } = await c.req.json<{ id: number; new_timestamp: string; remarks?: string }>();
        if (!id || !new_timestamp) {
            return c.json({ success: false, error: '需要提供记录 ID 和新的时间戳' }, 400);
        }
        
        // Optional: Add validation for the new_timestamp format
        
        const { success } = await c.env.DB.prepare(
            `UPDATE checkin_logs SET timestamp = ?, remarks = ? WHERE id = ?`
        ).bind(new_timestamp, remarks || null, id).run();

        if (success) {
            return c.json({ success: true });
        } else {
            return c.json({ success: false, error: '更新失败或记录不存在' }, 500);
        }
    } catch (e) {
        console.error('Update error:', e);
        return c.json({ success: false, error: e.message }, 500);
    }
});

/**
 * 接口 6: 获取统计数据 (GET /api/stats)
 */
app.get('/api/stats', async (c) => {
    try {
        // Note: All calculations are based on UTC time stored in the DB.
        // For higher accuracy with timezones, you might need a more complex setup.
        // The '+8 hours' modifier is used to adjust to Beijing time.

        // Adjust for Beijing Time (UTC+8) to correctly get the current date
        const now = new Date();
        const beijingTime = new Date(now.valueOf() + 8 * 60 * 60 * 1000);
        const year = beijingTime.getUTCFullYear();
        const month = String(beijingTime.getUTCMonth() + 1).padStart(2, '0');
        
        // D1 doesn't support Common Table Expressions (CTEs) as of my last update, 
        // so we have to run separate queries.

        // This Week's Count (strftime '%w' is 0 for Sunday, 1 for Monday...)
        // This logic assumes the week starts on Sunday.
        const weekStmt = c.env.DB.prepare(
            `SELECT COUNT(*) as count FROM checkin_logs WHERE strftime('%Y-%W', timestamp, '+8 hours') = strftime('%Y-%W', 'now', '+8 hours')`
        );

        // This Month's Count
        const monthStmt = c.env.DB.prepare(
            `SELECT COUNT(*) as count FROM checkin_logs WHERE strftime('%Y-%m', timestamp, '+8 hours') = ?`
        ).bind(`${year}-${month}`);

        // This Year's Count
        const yearStmt = c.env.DB.prepare(
            `SELECT COUNT(*) as count FROM checkin_logs WHERE strftime('%Y', timestamp, '+8 hours') = ?`
        ).bind(String(year));

        // Total Count
        const totalStmt = c.env.DB.prepare(
            `SELECT COUNT(*) as count FROM checkin_logs`
        );

        const [weekResult, monthResult, yearResult, totalResult] = await Promise.all([
            weekStmt.first<{ count: number }>(),
            monthStmt.first<{ count: number }>(),
            yearStmt.first<{ count: number }>(),
            totalStmt.first<{ count: number }>()
        ]);

        return c.json({
            success: true,
            stats: {
                thisWeek: weekResult?.count || 0,
                thisMonth: monthResult?.count || 0,
                thisYear: yearResult?.count || 0,
                total: totalResult?.count || 0,
            }
        });

    } catch (e) {
        console.error('Stats error:', e);
        return c.json({ success: false, error: e.message }, 500);
    }
});



export const onRequest: PagesFunction<Env> = (context) => {
  return app.fetch(context.request, context.env, context);
};
